/*
 * ModuleLoader.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */
package engine;

import java.io.*;
import java.util.*;

/**
 * This class is used for dynamically loading modules
 * from the known paths.
 * It also contains the writeModule methos, which writes
 * a module in the current working directory.
 */
class ModuleLoader
{
	/**
	 * The paths that will be searched for modules.
	 */
	public static Vector objPaths;

	/**
	 * Parses the "vide.libdirs" System property and
	 * puts the paths into objPaths.
	 */
	public static void setLibDirs() {
		objPaths = new Vector();
		objPaths.addElement("." + java.io.File.separatorChar);
		String home = System.getProperty("vide.libdir");
		if (home != null) {
			while (!home.equals("")) {
				int i = home.indexOf(':');
				if (i == -1) break;
				objPaths.addElement(home.substring(0, i));
				home = home.substring(i+1, home.length());
			}
		}
	}

	/**
	 * Resolves names to module descriptions
	 */
	public static ModuleFactory getModuleByName(String name) {
		ModuleFactory res = (ModuleFactory) VeriParser.moduleDescriptions.get(name);
		if (res == null) {
			xConsole.debug("reading module \"" + name + "\"");
			res = readModule(name);
			if (res != null)
				VeriParser.moduleDescriptions.put(name, res);
		}
		return res;
	}

	/**
	 * Finds a file that holds the given module,
	 * using the paths from objPaths (assumed to end with '/')
	 */
	public static String getModuleFile(String name) {
		name += ".vo";
		for (Enumeration e = objPaths.elements() ; e.hasMoreElements() ; ) {
			String s = e.nextElement() + name;
			if((new File(s)).exists()) return s;
		}
		return null;
	}

	/**
	 * Fetches a ModuleDescription from a file.
	 * The paths given in objPaths are searched for a match.
	 * @return null if no filename matches the module name.
	 */
	public static ModuleFactory readModule(String name) {
		String fileName = getModuleFile(name);
		ObjectInputStream oi = null;
		try {
			if (fileName != null) {
				return  (ModuleFactory)
				(oi = new ObjectInputStream(new FileInputStream(fileName))).
				readObject();
			}
		} catch (StreamCorruptedException scex) {
			throw new Error("error reading module \"" + fileName + "\". Bad file data");
		} catch (IOException ioex) {
			throw new Error("IO exception while reading module \"" +
					fileName + "\": " + ioex);
		}  catch (ClassNotFoundException cex){
			throw new Error(cex.toString());
		} finally {
			try {
				if (oi != null) oi.close();
			} catch (IOException ioex) {}
		}
		return null;
	}

	/**
	 * Dumps a moduleDescription to a file together with some magic &
	 * ver info. The file is created into the current directory !
	 */
	public static void writeModule(ModuleFactory desc) {
		ObjectOutputStream oo = null;
		String fileName = desc.name() + ".vo";
		try {
			oo = new ObjectOutputStream(new FileOutputStream(fileName));
			oo.writeObject(desc);
		} catch (IOException ioex) {
			throw new Error("IO exception while writing module \"" +
					fileName + "\": " + ioex);
		}
		finally {
			try {
				oo.close();
			} catch (IOException ioex) {}
		}
	}

}
